package com.yujie.filter;

import com.yujie.common.CommonStatus;
import com.yujie.security.LoginUser;
import com.yujie.utils.WebExceptionUtil;
import com.yujie.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    public JwtAuthenticationTokenFilter(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    private RedisTemplate<String,Object> redisTemplate;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //获取token
        String token = request.getHeader("token");
        if(Objects.isNull(token)){
            filterChain.doFilter(request,response);
            return;
        }
        String userId = null;
        try {
            //校验token是否有效
            Claims claims = JwtUtil.parseJWT(token);
            userId = claims.getSubject();
        } catch (Exception e) {
            e.printStackTrace();
            WebExceptionUtil.authenticateException("token非法",CommonStatus.EXCEPTION);
        }
        //从redis中获取
        String redisKey="loginUser:"+userId;
        LoginUser loginUser= (LoginUser) redisTemplate.opsForValue().get(redisKey);
        if(Objects.isNull(loginUser)){
            WebExceptionUtil.authenticateException("用户未登录",CommonStatus.EXCEPTION);
        }
        //挤掉token,判断是否是最新的token
        if(!loginUser.getNewToken().equals(token)){
            WebExceptionUtil.authenticateException("其他地方已登录,请从新登录",CommonStatus.EXCEPTION);
        }
        //token续期
        Long expire = redisTemplate.opsForValue().getOperations().getExpire(redisKey);
        if(expire==-2){
            WebExceptionUtil.authenticateException("token已过期,请从新登录",CommonStatus.EXCEPTION);
        }else {
            //过期时间不足10分钟,加1小时
            if(expire<60*10){
                redisTemplate.opsForValue().set(redisKey,loginUser,60*60, TimeUnit.SECONDS);
            }
        }
        //存入SecurityContextHolder为了让其他拦截器能识别已经认证通过
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser,null,null);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        filterChain.doFilter(request,response);
    }
}
